/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean.MrpSop;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import managedbean.Workspace.WorkspaceManagerBean;
import merlion.common.entity.Staff;
import merlion.common.session.stateless.SystemUserSessionBeanLocal;
import merlion.common.util.Consts;
import merlion.mrp.ppm.entity.ArchivedIndivSOP;
import merlion.mrp.ppm.entity.IndexNValue;
import merlion.mrp.ppm.entity.IndivSOP;
import merlion.mrp.ppm.entity.SOP;
import merlion.mrp.ppm.session.SalesOptPlanningSessionLocal;

/**
 *
 * @author Zhang Ying
 */
@ManagedBean
@ViewScoped
public class MrpSopViewManagerBean {

    public static final String SELECT_VIEW_SOP = "SelectedViewedSOP";
    public static final String EDIT_SOP = "EditedSOP";
    public static final String ARCHIVED_INDIVS = "ArchivedIndivs";
    @ManagedProperty(value = "#{workspaceManagerBean}")
    private WorkspaceManagerBean workspaceManagerBean;
    @EJB
    private SystemUserSessionBeanLocal suSession;
    @EJB
    private SalesOptPlanningSessionLocal mrpSopSession;
    // select view page
    private SOP viewedSOP;
    private String viewedSOPIDStr;
    private Collection<SOP> allSOPs;
    // view detail page
    private SOP selectedSOP;
    private List<Long> updatedTimes;
    private Long selectedUpdatedId;
    private ArrayList<String> monthLabels;
    //private ArrayList<ArrayList<Long>> seasonSalesForecasts;
    private ArrayList<Long> previousInventories;
    private ArrayList<Integer> workingDayList;
    // counters
    private ArrayList<Integer> counterForMonth; // 3
    private ArrayList<Integer> counterForProduct; // 4
    // for selecting sop for edition
    private SOP editedSOP;
    private String editedSOPIDStr;

    /** Creates a new instance of MrpSopViewManagerBean */
    public MrpSopViewManagerBean() {
        // init counters
        counterForMonth = new ArrayList<Integer>();
        for (int i = 0; i < 3; i++) {
            counterForMonth.add(new Integer(i));
        }
        counterForProduct = new ArrayList<Integer>();
        for (int i = 0; i < 4; i++) {
            counterForProduct.add(new Integer(i));
        }
        // init selected updated id
        selectedUpdatedId = new Long(0);
    }

    // select view page
    public String redirectToViewSOPDetail() {
        if (viewedSOPIDStr == null) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful", "Please select sales operation plan."));
            return null;
        }
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(SELECT_VIEW_SOP);
        viewedSOP = mrpSopSession.getMrpSop(viewedSOPIDStr);
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(SELECT_VIEW_SOP, viewedSOP);
        return getRedirectPath(Consts.VIEW_MRP_SOP_PATH + "Detail");
    }

    public Collection<SOP> getAllSOPs() {
        if (allSOPs == null) {
            allSOPs = mrpSopSession.getAllMrpSops();
        }
        return allSOPs;
    }

    public void setAllSOPs(Collection<SOP> allSOPs) {
        this.allSOPs = allSOPs;
    }

    public SOP getViewedSOP() {
        return viewedSOP;
    }

    public void setViewedSOP(SOP viewedSOP) {
        this.viewedSOP = viewedSOP;
        this.viewedSOPIDStr = viewedSOP.getSopIdStr();
    }

    public String getViewedSOPIDStr() {
        return viewedSOPIDStr;
    }

    public void setViewedSOPIDStr(String viewedSOPIDStr) {
        this.viewedSOPIDStr = viewedSOPIDStr;
    }

    // view detail page
    public SOP getSelectedSOP() {
        if (selectedSOP == null) {
            SOP temp = (SOP) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(SELECT_VIEW_SOP);
            if (temp != null) {
                selectedSOP = temp;
                changePeriodRelatedInfo(selectedSOP.getStartPeriodMonth());
            }
        }
        return selectedSOP;
    }

    public void setSelectedSOP(SOP selectedSOP) {
        this.selectedSOP = selectedSOP;
    }

    public Long getSelectedUpdatedId() {
        return selectedUpdatedId;
    }

    public void setSelectedUpdatedId(Long selectedUpdatedId) {
        this.selectedUpdatedId = selectedUpdatedId;
    }

    public List<Long> getUpdatedTimes() {
        List<ArchivedIndivSOP> archivedSOPs = (List<ArchivedIndivSOP>) getSelectedSOP().returnProductIndivSOP(0).getArchivedIndivSops();
        if (archivedSOPs == null || archivedSOPs.isEmpty()) {
            updatedTimes = new ArrayList<Long>();
            updatedTimes.add(new Long(0)); // 0 stands for the orginal copy
        } else {
            updatedTimes = new ArrayList<Long>();
            for (int i = 0; i < archivedSOPs.size() + 1; i++) {
                updatedTimes.add(new Long(i)); // 0 stands for the orginal copy
            }
        }
        return updatedTimes;
    }

    public void setUpdatedTimes(List<Long> updatedTimes) {
        this.updatedTimes = updatedTimes;
    }

    public String selectUpdatedVersionId(Long id) {
        setSelectedUpdatedId(id);
        return null;
    }

    public String returnUpdatedTime(Long id) {
        if (id.intValue() == 0) {
            return selectedSOP.getFormattedDay();
        } else {
            ArchivedIndivSOP asop = selectedSOP.returnProductIndivSOP(0).returnUpdateIndivs(id.intValue() - 1);
            if (asop == null) {
                return null;
            } else {
                return asop.getFormattedDay();
            }
        }
    }

    public String returnUpdatedOrOrigTitle(Long id) {
        if (id.intValue() == 0) {
            return "Latest Version ";
        } else {
            return "Archived Version " + id;
        }
    }

    public ArrayList<String> getMonthLabels() {
        return monthLabels;
    }

    public void setMonthLabels(ArrayList<String> monthLabels) {
        this.monthLabels = monthLabels;
    }

//    public ArrayList<ArrayList<Long>> getSeasonSalesForecasts() {
//        if (seasonSalesForecasts == null) {
//            
//            seasonSalesForecasts = mrpSopSession.getSeasonSalesForecastData(getSelectedSOP().getStartPeriodYear(), getSelectedSOP().getStartPeriodMonth());
//        }
//        return seasonSalesForecasts;
//    }
//
//    public void setSeasonSalesForecasts(ArrayList<ArrayList<Long>> seasonSalesForecasts) {
//        this.seasonSalesForecasts = seasonSalesForecasts;
//    }
    public ArrayList<Long> getPreviousInventories() {
        if (previousInventories == null) {
            previousInventories = mrpSopSession.getInventoryOfPrevSeasonLastMonth(getSelectedSOP().getStartPeriodYear(), getSelectedSOP().getStartPeriodMonth());
//            previousInventories = new ArrayList<Long>();
//            previousInventories.add(new Long(200));
//            previousInventories.add(new Long(150));
//            previousInventories.add(new Long(50));
//            previousInventories.add(new Long(100));
        }
        return previousInventories;
    }

    public void setPreviousInventories(ArrayList<Long> previousInventories) {
        this.previousInventories = previousInventories;
    }

    public ArrayList<Integer> getWorkingDayList() {
        if (workingDayList == null) {
            workingDayList = mrpSopSession.getWorkingDaysList(selectedSOP.getStartPeriodYear(), selectedSOP.getStartPeriodMonth());
        }
        return workingDayList;
    }

    public void setWorkingDayList(ArrayList<Integer> workingDayList) {
        this.workingDayList = workingDayList;
    }

    public ArrayList<Long> returnSelectedSalesForecast(Integer productCounter) {
        ArrayList<Long> result = new ArrayList<Long>();
        if (selectedUpdatedId.intValue() == 0) {
            for (IndexNValue inl : getSelectedSOP().returnProductIndivSOP(productCounter).getSalesforcastValues()){
                result.add(inl.getLongValue());
            }
        } else {
            for (IndexNValue inl : getSelectedSOP().returnProductIndivSOP(productCounter).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getSalesforcastValues()){
                result.add(inl.getLongValue());
            }
        }
        return result;
    }

    public ArrayList<Long> returnSelectedUnplannedDemand(Integer productCounter) {
        ArrayList<Long> result = new ArrayList<Long>();
        if (selectedUpdatedId.intValue() == 0) {
            for (IndexNValue inl : selectedSOP.returnProductIndivSOP(productCounter).getUnplannedDemandList()){
                result.add(inl.getLongValue());
            }
        } else {
            for (IndexNValue inl : selectedSOP.returnProductIndivSOP(productCounter).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getUnplannedDemandList()){
                result.add(inl.getLongValue());
            }
        }
        return result;
    }

    public ArrayList<Long> returnSelectedProductionPlan(Integer productCounter) {
        ArrayList<Long> result = new ArrayList<Long>();
        if (selectedUpdatedId.intValue() == 0) {
            for (IndexNValue inl :selectedSOP.returnProductIndivSOP(productCounter).getProductionPlanList()){
                result.add(inl.getLongValue());
            }
        } else {
            for (IndexNValue inl : selectedSOP.returnProductIndivSOP(productCounter).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getProductionPlanList()){
                result.add(inl.getLongValue());
            }
        }
        return result;
    }

    public ArrayList<Long> returnSelectedInventory(Integer productCounter) {
        ArrayList<Long> result = new ArrayList<Long>();
        if (selectedUpdatedId.intValue() == 0) {
            for (IndexNValue inl : selectedSOP.returnProductIndivSOP(productCounter).getInventoryList()){
                result.add(inl.getLongValue());
            }
        } else {
            for (IndexNValue inl : selectedSOP.returnProductIndivSOP(productCounter).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getInventoryList()){
                result.add(inl.getLongValue());
            }
        }
        return result;
    }

    public Long returnSelectedTotalDemand(Integer monthCounter, Integer productCounter) {
        Long sfVal, upVal;
        if (selectedUpdatedId.intValue() == 0) {
            sfVal = selectedSOP.returnProductIndivSOP(productCounter).getSalesforcastValues().get(monthCounter).getLongValue();
            upVal = selectedSOP.returnProductIndivSOP(productCounter).getUnplannedDemandList().get(monthCounter).getLongValue();
        } else {
            sfVal = selectedSOP.returnProductIndivSOP(productCounter).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getSalesforcastValues().get(monthCounter).getLongValue();
            upVal = selectedSOP.returnProductIndivSOP(productCounter).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getUnplannedDemandList().get(monthCounter).getLongValue();
        }
        return sfVal + upVal;
    }

    public Long returnCapacityWithNormalShift(Integer workingDay) {
        return (long) Consts.NORMAL_SHIFT_PER_DAY * workingDay;
    }

    public Long returnCapacityWithOTShift(Integer workingDay) {
        return (long) Consts.OVERTIME_SHIFT_PER_DAY * workingDay;
    }

    public Long returnSelectedTotalPlannedProductionHrs(Integer monthCounter) {
        Long sum = new Long(0);
        if (selectedUpdatedId.intValue() == 0) {
            for (int i = 0; i < 4; i++) {
                Long prodPlan = selectedSOP.returnProductIndivSOP(i).getProductionPlanList().get(monthCounter).getLongValue();
                //sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR);
                if (i == 0 || i == 1) {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_CLASSIC);
                } else {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_PREMIUM);
                }
            }
        } else {
            for (int i = 0; i < 4; i++) {
                Long prodPlan = selectedSOP.returnProductIndivSOP(i).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getProductionPlanList().get(monthCounter).getLongValue();
                //sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR);
                if (i == 0 || i == 1) {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_CLASSIC);
                } else {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_PREMIUM);
                }
            }
        }
        return sum;
    }

    public Double returnSelectedUtilizationWNormalShift(Integer monthCounter) {
        Long sum = new Long(0);
        if (selectedUpdatedId.intValue() == 0) {
            for (int i = 0; i < 4; i++) {
                Long prodPlan = selectedSOP.returnProductIndivSOP(i).getProductionPlanList().get(monthCounter).getLongValue();
                //sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR);
                if (i == 0 || i == 1) {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_CLASSIC);
                } else {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_PREMIUM);
                }
            }
        } else {
            for (int i = 0; i < 4; i++) {
                Long prodPlan = selectedSOP.returnProductIndivSOP(i).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getProductionPlanList().get(monthCounter).getLongValue();
                //sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR);
                if (i == 0 || i == 1) {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_CLASSIC);
                } else {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_PREMIUM);
                }
            }
        }
        Long cap = (long) Consts.NORMAL_SHIFT_PER_DAY * workingDayList.get(monthCounter);
        return 1.0 * sum / cap;
    }

    public Double returnSelectedUtilizatinWOTShift(Integer monthCounter) {
        Long sum = new Long(0);
        if (selectedUpdatedId.intValue() == 0) {
            for (int i = 0; i < 4; i++) {
                Long prodPlan = selectedSOP.returnProductIndivSOP(i).getProductionPlanList().get(monthCounter).getLongValue();
                //sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR);
                if (i == 0 || i == 1) {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_CLASSIC);
                } else {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_PREMIUM);
                }
            }
        } else {
            for (int i = 0; i < 4; i++) {
                Long prodPlan = selectedSOP.returnProductIndivSOP(i).returnUpdateIndivs(selectedUpdatedId.intValue() - 1).getProductionPlanList().get(monthCounter).getLongValue();
                //sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR);
                if (i == 0 || i == 1) {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_CLASSIC);
                } else {
                    sum += roundToLong(1.0 * prodPlan / Consts.CASES_PER_HOUR_PREMIUM);
                }
            }
        }
        Long cap = (long) Consts.OVERTIME_SHIFT_PER_DAY * workingDayList.get(monthCounter);
        return (1.0 * sum / cap);
    }

    // for general purpose
    private Long roundToLong(Double d) {
        return Math.round(d);
    }

    private String getRedirectPath(String path) {
        return path + "?faces-redirect=true";
    }

    public ArrayList<Integer> getCounterForMonth() {
        return counterForMonth;
    }

    public ArrayList<Integer> getCounterForProduct() {
        return counterForProduct;
    }

    public WorkspaceManagerBean getWorkspaceManagerBean() {
        return workspaceManagerBean;
    }

    public void setWorkspaceManagerBean(WorkspaceManagerBean workspaceManagerBean) {
        this.workspaceManagerBean = workspaceManagerBean;
    }

    private void changePeriodRelatedInfo(Integer month) {
        monthLabels = new ArrayList<String>();
        if (month.equals(1)) {
            monthLabels.add(Consts.DEC);
            monthLabels.add(Consts.JAN);
            monthLabels.add(Consts.FEB);
            monthLabels.add(Consts.MAR);
        } else if (month.equals(4)) {
            monthLabels.add(Consts.MAR);
            monthLabels.add(Consts.APR);
            monthLabels.add(Consts.MAY);
            monthLabels.add(Consts.JUN);
        } else if (month.equals(7)) {
            monthLabels.add(Consts.JUN);
            monthLabels.add(Consts.JUL);
            monthLabels.add(Consts.AUG);
            monthLabels.add(Consts.SEP);
        } else if (month.equals(10)) {
            monthLabels.add(Consts.SEP);
            monthLabels.add(Consts.OCT);
            monthLabels.add(Consts.NOV);
            monthLabels.add(Consts.DEC);
        }
    }

    public String returnProductAlpha(Integer i) {
        if (i.intValue() == 0) {
            return Consts.ProductType.BAR_A.getText();
        } else if (i.intValue() == 1) {
            return Consts.ProductType.BAR_B.getText();
        } else if (i.intValue() == 2) {
            return Consts.ProductType.BAR_C.getText();
        } else if (i.intValue() == 3) {
            return Consts.ProductType.BAR_D.getText();
        } else {
            return "";
        }
    }

    // for edited sop selected page
    public String redirectToEditSOPDetail() {
        if (editedSOPIDStr == null) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful", "Please select sales operation plan."));
            return null;
        }
        
        // check whether I am the one created it
//        Staff s = suSession.getStaff(workspaceManagerBean.getCurrentStaff().getId());
//        if (!s.getsOPs().contains(editedSOP)){
//            FacesContext.getCurrentInstance().addMessage(null,
//                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful", "Sorry, you are not the creator of this sop and cannot edit it."));
//            return null;
//        }
        
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(SELECT_VIEW_SOP);

        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(EDIT_SOP);
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(ARCHIVED_INDIVS);
        editedSOP = mrpSopSession.getMrpSop(editedSOPIDStr);
        
        // check whether able to edit the sop
        if (editedSOP.getAbleToEdit() == false){
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful", "Sorry. You are not allowed to change SOP now because you have update your daily MPS aleady."));
            return null;
        }
        
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(EDIT_SOP, editedSOP);

        // create new list of archived
        Calendar calendar = Calendar.getInstance();
        Date date = calendar.getTime();
        Timestamp currentTime = new Timestamp(date.getTime());

        ArrayList<ArchivedIndivSOP> archivedsops = new ArrayList<ArchivedIndivSOP>();
        
        // get archived number
        int archivedTimes;
        if (editedSOP.returnProductIndivSOP(0).getArchivedIndivSops() == null || editedSOP.returnProductIndivSOP(0).getArchivedIndivSops().isEmpty()){
            archivedTimes = 0;
        } else {
            archivedTimes = editedSOP.returnProductIndivSOP(0).getArchivedIndivSops().size();
        }
        for (int i = 0; i < 4; i++) {
            IndivSOP indivsop = editedSOP.returnProductIndivSOP(i);
            ArchivedIndivSOP temp = new ArchivedIndivSOP(archivedTimes ,currentTime, indivsop.getSalesforcastValues(), indivsop.getUnplannedDemandList(), indivsop.getProductionPlanList(), indivsop.getInventoryList());
            archivedsops.add(temp);
        }

        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(ARCHIVED_INDIVS, archivedsops);
        return getRedirectPath(Consts.EDIT_MRP_SOP_PATH + "Detail");
    }

    public SOP getEditedSOP() {
        return editedSOP;
    }

    public void setEditedSOP(SOP editedSOP) {
        this.editedSOP = editedSOP;
        this.editedSOPIDStr = editedSOP.getSopIdStr();
    }

    public String getEditedSOPIDStr() {
        return editedSOPIDStr;
    }

    public void setEditedSOPIDStr(String editedSOPIDStr) {
        this.editedSOPIDStr = editedSOPIDStr;
    }
}
